
#include <SI4735.h>
#include "Radio.h"
#include <OneButton.h>
#include "Console.h"

#if defined(ARDUINO_RASPBERRY_PI_PICO_W)  //Raspberry pi pico w

#define EC_KEY 13  //4
#define EC_S1 12   //2  //data
#define EC_S2 11   //3  //clk

#elif defined(ESP8266)  // ESP8266

#define EC_KEY 4
#define EC_S1 2  //data
#define EC_S2 3  //clk
#else

#define EC_KEY 4
#define EC_S1 2  //data
#define EC_S2 3  //clk

#endif

#define ST77XX_RED 0x001F
#define ST77XX_GREEN 0x07E0

OneButton SW(EC_KEY, true);


#define FREQ_MODE 0
#define VOLUME_MODE 1
#define AGC_MODE 2
#define BAND_WIDTH_MODE 3
#define BFO_MODE 4
#define AVC_MODE 5


///////////////////
#define STOP 0x0
#define _LSB 20
#define _USB 21
#define AGC 22
#define VOLUME 23
#define BAND 24
#define BFO 25
#define FREQ 26
#define RDS_OFF 27
#define RDS_ON 28
#define B1 29
#define B5 30
#define B10 31
#define B50 32
#define B100 33
#define B500 34
#define B1000 35
#define Radin_on 36
#define Radin_off 37
#define upfreq 38
#define downfreq 39
#define INPUT_FREQ 40
#define INPUT_END 60
#define INPUT_RESET 61
#define VOLUME_MAX 62
#define up 63
#define down 64
#define AVC 65

/////
#define FM_YGZS 70
#define FM_JJZS 71
#define FM_LNJTGB 72
#define FM_SYJTGB 73

//////////////////

//SSBRadio ssb;
Radio* radio;
Console* console;
char* freqName;
int buff;
uint16_t boffset = 1;
uint16_t currentVolume = 55;
uint8_t mode = FREQ;
bool input_freq = false;
char freq[5];
uint8_t freqIndex = 0;
bool rds = false;
bool isStatus = false;
bool xz = false;
bool ismode = false;
int8_t modeIndex = 0;
int8_t modelist[6] = {FREQ_MODE,VOLUME_MODE,AGC_MODE,BAND_WIDTH_MODE,BFO_MODE, AVC_MODE};


/**
98.6MHz
97.8MHz
94.8MHz
**/
void setup() {

  Serial.begin(9600);
  Serial2.setRX(5);
  Serial2.setTX(4);
  Serial2.begin(115200);
  //while (!Serial)
  console = new TaomuST7735();
  console->println("Hello Taomu Si4732");
  delay(100);

  pinMode(EC_S1, INPUT_PULLUP);
  pinMode(EC_S2, INPUT_PULLUP);

  SW.reset();
  SW.attachClick(click);
  SW.attachDoubleClick(doubleclick);
  SW.attachLongPressStop(longclick);
  SW.setDebounceTicks(20);
  SW.setClickTicks(200);
  SW.setPressTicks(500);
  radio = new Radio();
  delay(500);
  freqName = radio->change(0);      
  radio->setVolume(63);                                                                                                                                                                                        
  currentVolume = radio->getVolume();
  mode = FREQ_MODE;
  delay(500);
  attachInterrupt(digitalPinToInterrupt(EC_S1), encoderISR, CHANGE);
  show();
}



void click() {
  Serial.println("单击");
  currentVolume = radio->getVolume();
  Serial.println("currentVolume:" + String(currentVolume));
  radio->setVolume(0);
  show();
}

void longclick() {
  if(ismode){
    ismode = false;
    radio->setVolume(55);
  }else{
    ismode = true;
  }
}
void doubleclick() {
  // radio->autoFrequencyUp();
  // console->println(String(radio->getFrequency()), 4);
}
void show() {
  Serial.println("show status");
  console->print(radio->getFreqName(), 0, 30, 2);
  console->print((" " + String(radio->getVolume())).c_str(), 2);
  if (radio->getAGC() == 0) {
    console->print(" 0", ST77XX_RED, 2);
  } else {
    console->print((" " + String(radio->getAGC())).c_str(), ST77XX_GREEN, 2);
  }
  console->print((" " + String(radio->getAvcAmMaxGain())).c_str(), ST77XX_GREEN, 2);
  if (radio->isSSB()) {
    console->println((" " + String(radio->getSSB() == LSB ? "L" : "U")).c_str(), 2);
  }else{
    console->println(" ", 2);
  }
  console->print(("S" + String(radio->getSnr())).c_str(), 2);
  console->print((" R" + String(radio->getRssi())).c_str(), 2);
  if (radio->isSSB()) {
    console->println((" " + String(radio->getSSBBfo())).c_str(), 2);
  } else {
    console->println(" ", 2);
  }
  console->print(String(radio->getFrequency()).c_str(), 3);
  if (radio->isSSB() || radio->isAM()) {
    console->println((" " + String(radio->getBandWidth())).c_str(), 2);
  } else {
    console->println(" 0", 2);
  }
  //console->print(String(radio->rds()).c_str(), ST77XX_GREEN, 2);
  if (radio->isFM()) {
    if (rds) {
      console->print("RDS:", ST77XX_GREEN, 2);
      console->println(radio->rds(), ST77XX_GREEN, 2);
    } else {
      console->println("RDS", ST77XX_RED, 2);
    }
  }
}

void upMode(){
 if (mode == FREQ_MODE) {
      uint16_t freq = radio->getFrequency() + boffset;
      radio->setFrequency(freq);
      Serial.println("freq:"+String(freq));
    } else if (mode == BFO_MODE) {
      int bfo = radio->getSSBBfo();
      Serial.println("bfo:" + String(bfo));
      radio->setSSBBfo(bfo + 10);
    } else if (mode == VOLUME_MODE) {
      uint16_t vol = radio->getVolume();
      radio->setVolume(vol + 1);
      currentVolume = radio->getVolume();
      Serial.println("Volume:" + String(currentVolume));
    } else if (mode == BAND_WIDTH_MODE) {
      radio->bandWidth(1);
      Serial.println("band:" + String(radio->getBandWidth()));
    } else if (mode == AGC_MODE) {
      uint8_t agc = radio->getAGC();
      Serial.println("AGC:" + String(agc));
      radio->setAGC(agc + 1);
    }else if(mode == AVC_MODE){
      uint8_t avc = radio->getAvcAmMaxGain();
      radio->setAvcAmMaxGain(avc+1);
    }
     show();
}

void downMode(){
    Serial.println(mode);
    if (mode == FREQ_MODE) {
      uint16_t freq = radio->getFrequency() - boffset;
      radio->setFrequency(freq);
      Serial.println("freq:"+String(freq));
    } else if (mode == BFO_MODE) {
      int bfo = radio->getSSBBfo();
      Serial.println("bfo:" + String(bfo));
      radio->setSSBBfo(bfo - 10);
    } else if (mode == VOLUME_MODE && radio->getVolume() > 0) {
      uint16_t vol = radio->getVolume();
      radio->setVolume(vol - 1);
      currentVolume = radio->getVolume();
      Serial.println("Volume:" + String(currentVolume));
    } else if (mode == BAND_WIDTH_MODE) {
      radio->bandWidth(-1);
      Serial.println("band:" + String(radio->getBandWidth()));
    } else if (mode == AGC_MODE && radio->getAGC() > 0) {
      uint8_t agc = radio->getAGC();
      Serial.println("AGC:" + String(agc));
      radio->setAGC(agc - 1);
    }else if(mode == AVC_MODE){
      uint8_t avc = radio->getAvcAmMaxGain();
      radio->setAvcAmMaxGain(avc-1);
    }
     show();
}

#if defined(ESP8266)  // ESP8266 中断调用需要 IRAM_ATTR 加在函数开头
IRAM_ATTR void encoderISR() {
#else
void encoderISR() {
#endif

  if (digitalRead(EC_S1) == 0 && digitalRead(EC_S2) == 1) {
    if(!ismode){
     downMode();
    }else{
       if(modeIndex <= 0){
          modeIndex = 6;
       }
       mode = modelist[--modeIndex];
       Serial.println("d mode:" + String(mode)+" index"+String(modeIndex));
    }
    //delay(100);
   // show();
  } else if (digitalRead(EC_S1) == 0 && digitalRead(EC_S2) == 0) {
    if(!ismode){
      upMode();
    }else{
       if(modeIndex >= 6){
          modeIndex = -1;
       }
      mode = modelist[++modeIndex];
      Serial.println("u mode:" + String(mode)+" index"+String(modeIndex));
    }
    //  delay(100);
   // show();
  }
}

void voiceOptions(int buff,boolean xz){
 if (xz && !input_freq) {
    Serial.println("buff:"+String(buff));
    if(buff == FM_YGZS){
      freqName = radio->change(0);     
      radio->setFrequency(9480);
      show();
    }else if(buff == FM_JJZS){
      freqName = radio->change(0);     
      radio->setFrequency(9510);
      show();
    }else if(buff == FM_LNJTGB){
      freqName = radio->change(0);     
      radio->setFrequency(9750);
      show();
    }else if(buff == FM_SYJTGB){
      freqName = radio->change(0);     
      radio->setFrequency(9860);
      show();
    }else if (buff == upfreq) {
      Serial.println("autoFrequencyDown");
      radio->autoFrequencyUp();
      radio->bandWidth(0);
      Serial.println("freq:"+String(radio->getFrequency()));
      //delay(100);
     // radio->bandWidth(3);
      show();
    } else if (buff == downfreq) {
      Serial.println("autoFrequencyUp");
      radio->autoFrequencyDown();
      radio->bandWidth(0);
      Serial.println("freq:"+String(radio->getFrequency()));
     // delay(100);
     // radio->bandWidth(3);
     show();
    } else if (buff == AGC) {
      mode = AGC_MODE;
    } else if (buff == VOLUME) {
      mode = VOLUME_MODE;
    }else if(buff == AVC){
      mode = AVC_MODE;
    } else if (buff == B1) {
      boffset = 1;
    } else if (buff == B5) {
      boffset = 5;
    } else if (buff == B10) {
      boffset = 10;
    } else if (buff == B50) {
      boffset = 50;
    } else if (buff == B100) {
      boffset = 100;
    } else if (buff == B500) {
      boffset = 500;
    } else if (buff == B1000) {
      boffset = 1000;
    } else if (buff == BAND) {
      mode = BAND_WIDTH_MODE;
    } else if (buff == BFO) {
      mode = BFO_MODE;
    } else if (buff == FREQ) {
      mode = FREQ_MODE;
    } else if (buff == RDS_OFF) {
      rds = true;
      show();
    } else if (buff == RDS_ON) {
      rds = false;
      show();
    } else if (buff == _LSB) {
      radio->setSSB(LSB);
      show();
    } else if (buff == _USB) {
      radio->setSSB(USB);
      show();
    } else if (buff == Radin_off) {
      radio->off();
    } else if (buff == Radin_on) {
      radio->on();
    } else if (buff == INPUT_FREQ) {
      input_freq = true;
    } else if (buff == up) {
      upMode();
    } else if (buff == down) {
      downMode();
    } else if (buff == VOLUME_MAX) {
      radio->setVolume(63);
      currentVolume = 63;
      show();
    } else {
      radio->change2(buff, &show);
      mode = FREQ_MODE;
      //show();
    }
    radio->setVolume(currentVolume);
    Serial.println("mode:" + String(mode));
    //memset(buff, 0, sizeof(buff));
  } else if (xz && input_freq) {
    Serial.println("buff:"+String(buff));
    if (buff == INPUT_END) {
      Serial.println("INPUT END");
      freqIndex = 0;
      if (mode == FREQ_MODE) {
        uint16_t freqVal = atoi(freq);
        Serial.println("FREQ MODE:"+String(freqVal));
        radio->setFrequency(freqVal);
      } else if (mode == BFO_MODE) {
        int val = atoi(freq);
        Serial.println("BFO MODE:"+String(val));
        radio->setSSBBfo(val);
      } else if (mode == AGC_MODE) {
        uint8_t val = atoi(freq);
        Serial.println("AGC MODE:"+String(val));
        radio->setAGC(val);
      }
      memset(freq, 0, sizeof(freq));
      input_freq = false;
      show();
    } else if (buff == INPUT_RESET) {
      Serial.println("INPUT RESET");
      freqIndex = 0;
      memset(freq, 0, sizeof(freq));
    } else if (buff == '-' || (buff >= '0' && buff <= '9')) {
      if (freqIndex < 5) {
        freq[freqIndex++] = buff;
      }
      Serial.println("freqIndex:" + String(freqIndex) + "=>" + String(freq));
    }
    //memset(buff, 0, sizeof(buff));
  }
}

void serialOptions(){
  if(Serial.available()){
    char s = Serial.read();
    if(s == 's'){
      isStatus = !isStatus;
    }else if(s == 'u'){
      buff = upfreq;
      xz = true;
    }else if(s == 'd'){
      buff = downfreq;
      xz = true;
    }else if(s == 'l'){
      buff = FM_LNJTGB;
      xz = true;
    }else if(s == '='){
      buff = up;
      xz = true;
    }else if(s == '-'){
      buff = down;
      xz = true;
    }else if(s == 'a'){
      buff = AGC;
      xz = true;
     }else if(s == 'b'){
      buff = BAND;
      xz = true;
    }else if(s == 'v'){
      buff = VOLUME;
      xz = true;
     }else if(s == 'B'){
      buff = BFO;
      xz = true;
     }else if(s == 'f'){
      buff = FREQ;
      xz = true;
    }else if(s == 'F'){
      buff = FM0;
      xz = true;
    }else if(s == 'A'){
      buff = AM1;
      xz = true;
    }else if(s == 'S'){
      buff = SW4;
      xz = true;
    }else if(s == 'C'){
      buff = SSB18;
      xz = true;
     }else if(s == 'U'){
      uint8_t lu = radio->getSSB();
      if(lu == LSB){
        buff = _USB;
      }else{
        buff = _LSB;
      }
      xz = true;
    }else if(s == 'i'){
      buff = INPUT_FREQ;
      xz = true;
    }else if(s == 'e'){
      buff = INPUT_END;
      xz = true;
    }else if(input_freq){
      buff = s;
      xz = true;
    }
  }
}

// Main
void loop() {
  SW.tick();  //delay 时间长会导致按键失败
  // Serial.println("Si4732");
  int i = 0;
  xz = false;
  while (Serial2.available()) {
    buff = Serial2.read();
    Serial.println("Serial2 Read:" + String(buff));
    xz = true;
  }
  serialOptions();
  voiceOptions(buff, xz);
  if (!radio->isFM()) {
    rds = false;
  }
  if (rds) {
    //需要修改局部刷新与滚动效果
    show();
  }
  if(isStatus){
    radio->status();
  }
  delay(10);
}
